package stubcall

import (
	"sync"
	"sync/atomic"
)

var (
	callID uint32 = 1
)

type ClientStubCallMgr struct {
	callmap map[uint32]*ClientStubCall
	rwlock  sync.RWMutex
}

func NewClientStubCallMgr() *ClientStubCallMgr {
	csb := &ClientStubCallMgr{
		callmap: make(map[uint32]*ClientStubCall),
	}
	return csb
}

func (csm *ClientStubCallMgr) GetClientStubCall(callID uint32) *ClientStubCall {
	csm.rwlock.RLock()
	defer func() {
		csm.rwlock.RUnlock()
	}()
	v, ok := csm.callmap[callID]
	if ok {
		return v
	}
	return nil
}

func (csm *ClientStubCallMgr) RemoveAll(srvID uint32) {
	csm.rwlock.Lock()
	defer func() {
		csm.rwlock.Unlock()
	}()
	for k, v := range csm.callmap {
		if v.stubID == srvID {
			delete(csm.callmap, k)
		}
	}
}

func (csm *ClientStubCallMgr) CleanUp() {

	csm.rwlock.Lock()
	defer func() {
		csm.rwlock.Unlock()
	}()

	csm.callmap = make(map[uint32]*ClientStubCall)
}

func (csm *ClientStubCallMgr) Destory(callID uint32) {
	csm.rwlock.Lock()
	defer func() {
		csm.rwlock.Unlock()
	}()

	if _, ok := csm.callmap[callID]; ok {
		delete(csm.callmap, callID)
	}
}

//@title stubcall 管理器
func (csm *ClientStubCallMgr) Add(call *ClientStubCall) *ClientStubCall {
	if call == nil {
		return nil
	}

	//赋值 赋予对应的 id
	call.callID = atomic.AddUint32(&callID, 1)

	csm.rwlock.Lock()
	defer func() {
		csm.rwlock.Unlock()
	}()

	if _, ok := csm.callmap[call.callID]; ok {
		//TODO deal dup
		return nil
	}
	csm.callmap[call.callID] = call
	return call
}
